package com.linking.third.party.manager;

import com.braintreegateway.BraintreeGateway;
import com.braintreegateway.Environment;
import com.braintreegateway.Result;
import com.braintreegateway.Transaction;
import com.braintreegateway.TransactionRequest;
import com.google.common.collect.Maps;
import com.linking.third.party.pojo.bo.PaypalBO;
import com.linking.third.party.pojo.bo.ReceiptVerifyBO;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;

/**
 * @Author YaoWeiXin
 * @Date 2020/6/18 14:32
 * @Description Paypal管理类
 */
@Slf4j
public class PaypalManager {

  private static Map<String, BraintreeGateway> cacheGateway = Maps.newHashMap();
  private static Map<String, BraintreeGateway> cacheGateway2 = Maps.newHashMap();

  private static BraintreeGateway getGateway(String accessToken) {
    BraintreeGateway gateway;
    if (cacheGateway.containsKey(accessToken)) {
      gateway = cacheGateway.get(accessToken);
    } else {
      gateway = new BraintreeGateway(accessToken);
      cacheGateway.put(accessToken, gateway);
    }
    return gateway;
  }

  private static BraintreeGateway getGateway(String merchantId,
      String publicKey, String privateKey, Boolean sendBox) {
    BraintreeGateway gateway;
    if (cacheGateway2.containsKey(merchantId)) {
      gateway = cacheGateway2.get(merchantId);
    } else {
      gateway = new BraintreeGateway(sendBox ? Environment.SANDBOX : Environment.PRODUCTION,
          merchantId, publicKey, privateKey);
      cacheGateway2.put(merchantId, gateway);
    }
    return gateway;
  }

  /**
   * 生成客户端token
   *
   * @param accessToken token
   * @return 客户端token
   */
  public static String createClientToken(String accessToken) {
    BraintreeGateway gateway = getGateway(accessToken);
    return createClientToken(gateway);
  }

  /**
   * 生成客户端token
   *
   * @param merchantId 商户号
   * @param publicKey  公钥
   * @param privateKey 私钥
   * @param sendBox    环境
   * @return 客户端token
   */
  public static String createClientToken(String merchantId, String publicKey, String privateKey,
      Boolean sendBox) {
    BraintreeGateway gateway = getGateway(merchantId, publicKey, privateKey, sendBox);
    return createClientToken(gateway);
  }

  private static String createClientToken(BraintreeGateway gateway) {
    return gateway.clientToken().generate();
  }

  /**
   * 票据验证
   *
   * @param accessToken token
   * @param paypal      paypal支付对象
   * @return true|false
   */
  public static ReceiptVerifyBO receiptVerify(String accessToken, PaypalBO paypal) {
    try {
      BraintreeGateway gateway = getGateway(accessToken);
      return receiptVerify(gateway, paypal);
    } catch (Exception e) {
      log.info("Paypal receiptVerify failure = {0}", e);
      return ReceiptVerifyBO.ofFail();
    }
  }

  /**
   * 票据验证
   *
   * @param merchantId  商户号
   * @param publicKey   公钥
   * @param privateKey  私钥
   * @param sendBox    环境
   * @param paypal      paypal支付对象
   * @return true|false
   */
  public static ReceiptVerifyBO receiptVerify(String merchantId,
      String publicKey, String privateKey, Boolean sendBox, PaypalBO paypal) {
    try {
      BraintreeGateway gateway = getGateway(merchantId, publicKey, privateKey, sendBox);
      return receiptVerify(gateway, paypal);
    } catch (Exception e) {
      log.info("Paypal receiptVerify failure = {0}", e);
      return ReceiptVerifyBO.ofFail();
    }
  }

  private static ReceiptVerifyBO receiptVerify(BraintreeGateway gateway, PaypalBO paypal) {
    if (paypal.getLog()) {
      log.debug("receiptVerify============{},{}", paypal.getAmount(), paypal.getPaymentMethodNonce());
    }
    TransactionRequest request = new TransactionRequest()
        .amount(paypal.getAmount())
        .paymentMethodNonce(paypal.getPaymentMethodNonce())
        .options()
        .submitForSettlement(true)
        .done();
    Result<Transaction> saleResult = gateway.transaction().sale(request);
    if (!saleResult.isSuccess()) {
      log.debug("receiptVerify fail============{}", saleResult.getMessage());
      // 验证未成功
      return ReceiptVerifyBO.ofFail();
    }
    Transaction transaction = saleResult.getTarget();
    if (paypal.getLog()) {
      log.debug("receiptVerify ok============{},{}", transaction.getOrderId(), paypal.getProductId());
    }
    return ReceiptVerifyBO.of(true, transaction.getOrderId(), paypal.getProductId());
  }
}
